package gameframe;

import client.ClientPlayer;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Hsu琛君珩
 * @ClassName:LoginFrame
 * @date 2023-12-21
 * @apiNote
 * @Version: v1.0
 */

/**
 * 登录窗口类。
 * 负责创建和管理用户登录界面，包括输入字段和登录/注册按钮。
 */
public class LoginFrame extends JFrame {
    private static LoginFrame instance; // 登录窗口的单例实例

    private JPanel userInputFrame;             // 用户输入面板，包含用户名和密码输入字段
    private JPanel buttonFrame;                // 按钮面板，包含登录和注册按钮
    private JLabel userNameLabel;              // 用户名标签，标识用户名输入字段
    private JLabel userPasswordLabel;          // 密码标签，标识密码输入字段
    private JTextField userNameTextField;      // 用户名文本字段，用户输入用户名
    private JPasswordField userPasswordTextField; // 密码字段，用户输入密码，输入内容以点显示以保护隐私
    private JButton loginButton;               // 登录按钮，触发登录逻辑
    private JButton registerButton;            // 注册按钮，触发注册逻辑

    /**
     * 获取LoginFrame的单例实例。
     * 如果实例不存在，则创建一个新实例。
     *
     * @return LoginFrame的单例实例
     */
    public static LoginFrame getInstance() {
        if (instance == null) {
            instance = new LoginFrame();
        }
        return instance;
    }

    /**
     * 构造方法，私有化以防止外部直接创建实例。
     * 初始化登录界面的组件。
     */
    private LoginFrame() {
        initializeComponents();
        initActionListener();
    }

    /**
     * 初始化组件。
     * 创建并配置登录界面的各个组件，包括文本字段和按钮。
     */
    private void initializeComponents() {
        // 设置登录窗口的标题。
        this.setTitle("登录");
        // 设置登录窗口在屏幕上的位置。
        this.setLocation(500, 200);
        // 设置登录窗口的尺寸。
        this.setSize(new Dimension(300, 300));
        // 设置登录窗口的图标。
        this.setIconImage(new ImageIcon("image/logo.jpg").getImage());
        // 禁止调整登录窗口的大小。
        this.setResizable(false);
        // 设置当用户点击关闭按钮时的默认操作，这里是退出应用程序。
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        // 创建一个新的面板，用于用户输入，布局为2行1列的网格。
        userInputFrame = new JPanel(new GridLayout(2, 1));
        // 创建并设置用户名和密码的标签。
        userNameLabel = new JLabel("用户名");
        userPasswordLabel = new JLabel("密码");
        // 创建文本框供用户输入用户名和密码。
        userNameTextField = new JTextField();
        userPasswordTextField = new JPasswordField();
        // 设置用户名和密码标签及对应文本框的大小。
        setLabelAndFieldSize(userNameLabel, userNameTextField);
        setLabelAndFieldSize(userPasswordLabel, userPasswordTextField);
        // 将标签和文本框组合成一个面板，并添加到用户输入面板中。
        userInputFrame.add(createInputPanel(userNameLabel, userNameTextField));
        userInputFrame.add(createInputPanel(userPasswordLabel, userPasswordTextField));
        // 创建一个新的面板，用于放置登录和注册按钮。
        buttonFrame = new JPanel();
        loginButton = new JButton("登录");
        registerButton = new JButton("注册");
        buttonFrame.add(loginButton);
        buttonFrame.add(registerButton);
        // 将用户输入面板和按钮面板添加到登录窗口的内容面板中。
        this.getContentPane().add(userInputFrame, BorderLayout.CENTER);
        this.getContentPane().add(buttonFrame, BorderLayout.SOUTH);
    }

    /**
     * 设置标签和文本字段的大小。
     *
     * @param label   标签
     * @param textField 文本字段
     */
    private void setLabelAndFieldSize(JLabel label, JTextField textField) {
        label.setPreferredSize(new Dimension(75, 50));
        textField.setPreferredSize(new Dimension(150, 50));
    }

    /**
     * 创建包含标签和文本字段的面板。
     *
     * @param label   标签
     * @param textField 文本字段
     * @return 包含标签和文本字段的面板
     */
    private JPanel createInputPanel(JLabel label, JTextField textField) {
        JPanel panel = new JPanel();
        panel.add(label);
        panel.add(textField);
        return panel;
    }

    /**
     * 初始化事件监听。
     * 为登录和注册按钮添加事件处理程序。
     */
    private void initActionListener() {
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                handleLogin();
            }
        });

        registerButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                handleRegister();
            }
        });
    }

    /**
     * 处理登录操作。
     * 该方法负责验证用户输入的用户名和密码，并进行登录验证。
     */
    private void handleLogin() {
        // 从文本框获取用户输入的用户名和密码，并去除两端的空白字符。
        String userName = userNameTextField.getText().trim();
        String password = new String(userPasswordTextField.getPassword()).trim();

        // 检查用户名和密码是否为空。
        if (userName.isEmpty() || password.isEmpty()) {
            // 如果任一为空，则显示错误消息，并中止登录操作。
            JOptionPane.showMessageDialog(this, "用户名或密码不能为空！食懵你啊！", "登录错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 调用userLoginVerify()方法进行登录验证。
        if (userLoginVerify(userName, password)) {
            // 如果验证成功，设置当前用户并进入游戏大厅。
            ClientPlayer.getInstance().setUserName(userName);
            ClientPlayer.getInstance().enterGameLobby();
            this.setVisible(false); // 隐藏登录窗口。
        } else {
            // 如果验证失败，显示错误消息。
            JOptionPane.showMessageDialog(this, "用户名或密码错误！食懵你啊！", "登录失败", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 处理注册操作。
     * 该方法负责验证用户输入的用户名和密码，并进行注册验证。
     */
    private void handleRegister() {
        // 从文本框获取用户输入的用户名和密码，并去除两端的空白字符。
        String userName = userNameTextField.getText().trim();
        String password = new String(userPasswordTextField.getPassword()).trim();

        // 检查用户名和密码是否为空。
        if (userName.isEmpty() || password.isEmpty()) {
            // 如果任一为空，则显示错误消息，并中止注册操作。
            JOptionPane.showMessageDialog(this, "用户名或密码不能为空！食懵你啊！", "注册错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 调用userRegisterVerify()方法进行注册验证。
        if (userRegisterVerify(userName, password)) {
            // 如果注册成功，询问用户是否直接登录。
            int option = JOptionPane.showConfirmDialog(this, "注册成功！\n是否现在登录？醒目仔！", "注册成功", JOptionPane.YES_NO_OPTION);
            if (option == JOptionPane.YES_OPTION) {
                // 如果用户选择登录，设置当前用户并进入游戏大厅。
                ClientPlayer.getInstance().setUserName(userName);
                ClientPlayer.getInstance().enterGameLobby();
                this.setVisible(false); // 隐藏登录窗口。
            }
        } else {
            // 如果注册失败，显示错误消息。
            JOptionPane.showMessageDialog(this, "用户名已存在！食懵你啊！", "注册失败", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 用户登录验证。
     * 向服务器发送登录请求并验证响应。
     *
     * @param userName 用户名
     * @param password 密码
     * @return 验证是否通过
     */
    private boolean userLoginVerify(String userName, String password) {
        // 将密码转换为哈希值或其他安全形式
        String hashedPassword = Integer.toString(password.hashCode());
        // 发送登录请求并接收验证结果
        return ClientPlayer.getInstance().loginVerify(userName, hashedPassword);
    }

    /**
     * 用户注册验证。
     * 向服务器发送注册请求并验证响应。
     *
     * @param userName 用户名
     * @param password 密码
     * @return 验证是否通过
     */
    private boolean userRegisterVerify(String userName, String password) {
        // 将密码转换为哈希值或其他安全形式
        String hashedPassword = Integer.toString(password.hashCode());
        // 发送注册请求并接收验证结果
        return ClientPlayer.getInstance().registerVerify(userName, hashedPassword);
    }

}